using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace CollabApp.Domain.Entities;

/// <summary>
/// 通知实体类 - 存储发送给用户的各种系统通知和消息
/// 支持多种通知类型和状态管理
/// </summary>
[Table("notifications")]
public class Notification : BaseEntity
{
    /// <summary>
    /// 用户ID - 接收通知的用户
    /// </summary>
    [Required]
    [Column("user_id")]
    public Guid UserId { get; private set; }

    /// <summary>
    /// 通知类型 - 通知的分类和用途
    /// </summary>
    [Required]
    [Column("notification_type")]
    public NotificationType NotificationType { get; private set; }

    /// <summary>
    /// 通知标题 - 通知的主题或标题
    /// </summary>
    [Required]
    [MaxLength(100)]
    [Column("title")]
    public string Title { get; private set; } = string.Empty;

    /// <summary>
    /// 通知内容 - 通知的详细内容或描述
    /// </summary>
    [Required]
    [MaxLength(500)]
    [Column("content")]
    public string Content { get; private set; } = string.Empty;

    /// <summary>
    /// 是否已读 - 标记用户是否已经查看该通知
    /// </summary>
    [Column("is_read")]
    public bool IsRead { get; private set; } = false;

    /// <summary>
    /// 相关数据 - 通知相关的额外数据，JSON格式存储
    /// 例如：游戏ID、房间ID、用户ID等相关联的信息
    /// </summary>
    [Column("data", TypeName = "json")]
    public string? Data { get; private set; }

    /// <summary>
    /// 阅读时间 - 用户查看通知的时间
    /// </summary>
    [Column("read_at")]
    public DateTime? ReadAt { get; private set; }

    // ============ 构造函数 ============

    /// <summary>
    /// 无参构造函数 - EF Core 必需
    /// </summary>
    private Notification() { }

    /// <summary>
    /// 私有构造函数 - 仅限工厂方法调用
    /// </summary>
    /// <param name="userId">用户ID</param>
    /// <param name="notificationType">通知类型</param>
    /// <param name="title">通知标题</param>
    /// <param name="content">通知内容</param>
    /// <param name="data">相关数据</param>
    private Notification(Guid userId, NotificationType notificationType, string title, string content, string? data = null)
    {
        UserId = userId;
        NotificationType = notificationType;
        Title = title;
        Content = content;
        IsRead = false;
        Data = data;
        ReadAt = null;
    }

    // ============ 导航属性 ============
    
    /// <summary>
    /// 导航属性 - 接收通知的用户
    /// </summary>
    [ForeignKey("UserId")]
    public virtual Auth.User User { get; set; } = null!;

    // ============ 工厂方法 ============

    /// <summary>
    /// 创建新通知 - 工厂方法
    /// </summary>
    /// <param name="userId">用户ID</param>
    /// <param name="notificationType">通知类型</param>
    /// <param name="title">通知标题</param>
    /// <param name="content">通知内容</param>
    /// <param name="data">相关数据</param>
    /// <returns>新通知实例</returns>
    public static Notification CreateNotification(Guid userId, NotificationType notificationType, 
                                                   string title, string content, string? data = null)
    {
        if (userId == Guid.Empty)
            throw new ArgumentException("用户ID不能为空", nameof(userId));
        if (string.IsNullOrWhiteSpace(title))
            throw new ArgumentException("通知标题不能为空", nameof(title));
        if (string.IsNullOrWhiteSpace(content))
            throw new ArgumentException("通知内容不能为空", nameof(content));

        return new Notification(userId, notificationType, title, content, data);
    }

    // ============ 业务方法 ============

    /// <summary>
    /// 标记为已读
    /// </summary>
    public void MarkAsRead()
    {
        if (!IsRead)
        {
            IsRead = true;
            ReadAt = DateTime.UtcNow;
        }
    }

    /// <summary>
    /// 标记为未读
    /// </summary>
    public void MarkAsUnread()
    {
        if (IsRead)
        {
            IsRead = false;
            ReadAt = null;
        }
    }

    /// <summary>
    /// 检查通知是否过期（创建超过30天）
    /// </summary>
    /// <returns>是否过期</returns>
    public bool IsExpired()
    {
        return (DateTime.UtcNow - CreatedAt).TotalDays > 30;
    }

    /// <summary>
    /// 获取通知类型的显示名称
    /// </summary>
    /// <returns>类型名称</returns>
    public string GetNotificationTypeName()
    {
        return NotificationType switch
        {
            NotificationType.System => "系统通知",
            NotificationType.RankingChange => "排名变化",
            NotificationType.Achievement => "成就解锁",
            NotificationType.GameResult => "游戏结果",
            _ => "未知类型"
        };
    }
}

/// <summary>
/// 通知类型枚举 - 定义不同种类的系统通知
/// </summary>
public enum NotificationType
{
    /// <summary>
    /// 系统通知 - 来自系统的重要消息
    /// </summary>
    System,
    
    /// <summary>
    /// 排名变化 - 用户排名发生变化的通知
    /// </summary>
    RankingChange,
    
    /// <summary>
    /// 成就解锁 - 获得新成就的通知
    /// </summary>
    Achievement,
    
    /// <summary>
    /// 游戏结果 - 游戏结束后的结果通知
    /// </summary>
    GameResult
}
